package com.example.init;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.example.anno.RequestMapping;
import com.example.listener.MyServletContextListener;
import com.example.util.ConfigUtil;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Context;
import org.apache.catalina.core.DefaultInstanceManager;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.SimpleInstanceManager;
import org.reflections.Reflections;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Slf4j
public class InitTomcat {
    public static Context context;
    public void startTomcat() throws Exception {
        ServerConfig serverConfig = ConfigUtil.getConfig("server", ServerConfig.class);
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(serverConfig.getPort());
        tomcat.getConnector(); // 创建默认连接器

        // 添加 Web 应用上下文
        Context ctx = tomcat.addContext("", new File(serverConfig.getPath()).getAbsolutePath());
//        ctx.addApplicationListener("com.example.listener.MyServletContextListener");
        //或者下面的方式
//        ctx.addApplicationListener(MyServletContextListener.class.getName());

        //记录一下context
        context = ctx;
        //添加filter
        scanFilter(ctx);

        // 添加 Servlet
        Tomcat.addServlet(ctx, "hello", new HttpServlet() {
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//                RedisUtil.set("a","hello world");
//                String s = RedisUtil.get("a");
                resp.getWriter().println("<h1>Hello from embedded Tomcat</h1>" );
            }
        });
        ctx.addServletMappingDecoded("/hello", "hello");

        List<ServletBean> servletBeanList = scanHttpServlet();
        for(ServletBean servletBean : servletBeanList) {
            String url = servletBean.getUrl();
            String name = servletBean.getBeanName();
            Servlet servlet = servletBean.getServlet();
            Tomcat.addServlet(ctx, name, servlet);
            ctx.addServletMappingDecoded(url, name);
        }

//        Tomcat.addServlet(ctx, "queryServlet", new QueryParamServlet());
//        ctx.addServletMappingDecoded("/query", "queryServlet");
//
//        Tomcat.addServlet(ctx, "formServlet", new FormParamServlet());
//        ctx.addServletMappingDecoded("/form", "formServlet");
//
//        Tomcat.addServlet(ctx, "jsonServlet", new JsonServlet());
//        ctx.addServletMappingDecoded("/json", "jsonServlet");
//
//        Tomcat.addServlet(ctx, "uploadServlet", new UploadServlet());
//        ctx.addServletMappingDecoded("/upload", "uploadServlet");
//        ServletRegistration.Dynamic reg =
//                (ServletRegistration.Dynamic) ctx.getServletContext().getServletRegistration("uploadServlet");
//        reg.setMultipartConfig(new MultipartConfigElement(
//                System.getProperty("java.io.tmpdir"),
//                10 * 1024 * 1024,
//                10 * 1024 * 1024,
//                0));

        tomcat.start();
        tomcat.getServer().await(); // 阻塞主线程，防止退出
    }

    /**
     * 扫描servlet
     * @return
     */
    private List<ServletBean> scanHttpServlet() {
        Reflections reflections = new Reflections("com.example.myservlet");
        Set<Class<? extends HttpServlet>> servlets =
                reflections.getSubTypesOf(HttpServlet.class);

        //使用hutool扫描，会扫描到子类
//        Set<Class<?>> allClasses = ClassUtil.scanPackage("com.example");
//        Set<Class<?>> servletClasses = allClasses.stream()
//                .filter(HttpServlet.class::isAssignableFrom)
//                .collect(Collectors.toSet());

        List<ServletBean> servletBeanList = new ArrayList<>();
        for(Class servletClass : servlets) {
            ServletBean bean = new ServletBean();
            String[] split = servletClass.getName().split("\\.");
            String name = StrUtil.lowerFirst(split[split.length-1]);
            Object newInstance = ReflectUtil.newInstance(servletClass);

            String url = "";
            if(servletClass.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping requestMapping = (RequestMapping) servletClass.getAnnotation(RequestMapping.class);
                url = requestMapping.value();
            }
            bean.setUrl(url);
            bean.setBeanName(name);
            bean.setServlet((Servlet)newInstance);
            servletBeanList.add(bean);
        }
        servlets.forEach(c -> log.info(c.getName()));
        return servletBeanList;
    }

    /**
     * 扫描filter
     * @param ctx
     */
    private void scanFilter(Context ctx) {
//        ServletContext servletContext = ctx.getServletContext();
//        servletContext.addFilter("SaTokenContextFilterForServlet", new SaTokenContextFilterForServlet())
//                .addMappingForUrlPatterns(null, true, "/*");

        // 创建FilterDef
//        FilterDef filterDef = new FilterDef();
//        filterDef.setFilterName("SaTokenContextFilterForServlet");
//        filterDef.setFilterClass(SaTokenContextFilterForServlet.class.getName());
//        filterDef.setFilter(new SaTokenContextFilterForServlet());
//        ctx.addFilterDef(filterDef);
//
//        // 创建FilterMap
//        FilterMap filterMap = new FilterMap();
//        filterMap.setFilterName("SaTokenContextFilterForServlet");
//        filterMap.addURLPattern("/*");
//        filterMap.setDispatcher(DispatcherType.REQUEST.name());
//        ctx.addFilterMap(filterMap);
    }

}
